﻿using General.Core.Config;
using General.Core.Data;
using General.Entities.Data;
using General.Entities.Models;
using General.Entities.ViewData.Admin;
using General.Entities.ViewData.Article;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace General.Services.Article
{
    public class ArticleService : IArticleService
    {
        private readonly IRepository<tc_article> tc_ArticleRepository;
        private readonly IRepository<tc_articlecate> tc_ArticlecateRepository;
        private readonly IRepository<tc_admin> tc_AdminRepository;
        private readonly IMemoryCache memoryCache;

        public ArticleService(IRepository<tc_article> tc_articleRepository,
            IRepository<tc_articlecate> tc_articlecateRepository,
            IRepository<tc_admin> tc_adminRepository,
            IMemoryCache memoryCache)
        {
            tc_ArticleRepository = tc_articleRepository;
            tc_ArticlecateRepository = tc_articlecateRepository;
            tc_AdminRepository = tc_adminRepository;
            this.memoryCache = memoryCache;
        }


        /// <summary>
        /// 获取列表信息    
        /// </summary>
        /// <param name="page"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public async Task<AdminResult> GetList(DateTime? startTime, DateTime? endTime, int page, int limit, string title,int cateId=-1, int status = -1, int ontop = -1, int iselite = -1)
        {
            AdminResult result = new AdminResult();
            var query = from a in tc_ArticleRepository.Table
                        join c in tc_ArticlecateRepository.Table on a.cateId equals c.id
                        join u in tc_AdminRepository.Table on a.author equals u.id into userGroup
                        from user in userGroup.DefaultIfEmpty()
                        where !string.IsNullOrWhiteSpace(title) ? a.title.Contains(title) : true && status!=-1 ? a.status==status:true && cateId != -1 ? a.cateId == cateId : true && ontop != -1 ? a.ontop == ontop : true && iselite != -1 ? a.iselite == iselite : true && ((startTime!=null && endTime!=null) ? (a.createTime>= startTime && a.createTime <= endTime) :true)
                        orderby a.id descending
                        select new ArticleModel()
                        {
                            id = a.id,
                             cateId = a.cateId,
                              title = a.title,
                               subhead=a.subhead,
                                intro = a.intro,
                                 author = a.author,
                            cateName = c.name,
                             nickname= user ==null ? "无":user.nickname,
                              copyfrom=a.copyfrom,
                               description=a.description, hits = a.hits, iselite = a.iselite,
                                keyWords=a.keyWords, ontop = a.ontop,
                            thumb = a.thumb, updateTime = a.updateTime,
                            createTime = a.createTime,
                            status = a.status,
                        };
            result.count = await query.CountAsync();
            result.data = await query.Skip((page - 1) * limit).Take(limit).ToListAsync();
            result.code = 0;
            return result;

        }


        /// <summary>
        /// 获取最新文章
        /// </summary>
        /// <returns></returns>
        public async Task<List<SimpleArticleInfo>> GetNewList(int limit=10, int page = 1, int? cate=null,string? search=null)
        {
            var query = from a in tc_ArticleRepository.Table
                        join c in tc_ArticlecateRepository.Table on a.cateId equals c.id
                        join u in tc_AdminRepository.Table on a.author equals u.id into userGroup
                        from user in userGroup.DefaultIfEmpty()
                        where a.status == 1 && (cate==null?true:c.id==cate) && (string.IsNullOrEmpty(search) ? true : a.title.ToLower().Contains(search.ToLower()))
                        orderby a.id descending
                        select new SimpleArticleInfo()
                        {
                            creatTime = a.createTime.ToString("yyyy-MM-dd"),
                            hits = a.hits,
                            id = a.id,
                            thumb = a.thumb,
                            title = a.title, userImage = user.headimg, username = user.nickname,
                              cateId = c.id, cateName = c.name
                        };
            return await query.Skip((page - 1) * limit).Take(limit).ToListAsync();
        }

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task AddInfo(tc_article model)
        {
            model.createTime = DateTime.Now;
            model.updateTime = DateTime.Now;
            await tc_ArticleRepository.insertAsync(model);
            //增加文章量
            var cateModel = await tc_ArticlecateRepository.getByIdAsync(model.cateId);
            cateModel.count++;
            await tc_ArticlecateRepository.UpdateAsync(cateModel);
        }


        /// <summary>
        /// 根据id获取文章内容
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<string> GetArticleContent(int id)
        {
            var model = await tc_ArticleRepository.getByIdAsync(id);
            return model.content;
        }

        /// <summary>
        /// 根据id获取文章详细信息 渲染前端
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ArticleInfo> GetArticleInfoById(int id)
        {
            var result = await tc_ArticleRepository.GetAsync(x=>x.id==id);
            var query = from a in tc_ArticleRepository.Table
                        join c in tc_ArticlecateRepository.Table on a.cateId equals c.id
                        join u in tc_AdminRepository.Table on a.author equals u.id into userGroup
                        from user in userGroup.DefaultIfEmpty()
                        where a.id==id
                        select new ArticleInfo()
                        {
                            id = a.id,
                            cateId = a.cateId,
                            title = a.title,
                            subhead = a.subhead,
                            intro = a.intro,
                            author = a.author,
                            cateName = c.name,
                            nickname = user == null ? "无" : user.nickname,
                            userImage = user == null ? "/images/user.png": user.headimg,
                            copyfrom = a.copyfrom,
                            description = a.description,
                            hits = a.hits,
                            iselite = a.iselite,
                            keyWords = a.keyWords,
                            ontop = a.ontop,
                            thumb = a.thumb,
                            updateTime = a.updateTime,
                            createTime = a.createTime,
                            status = a.status,
                            content = a.content
                        };
            var articleInfo = await query.FirstOrDefaultAsync();
            if (articleInfo==null)
            {
                return null;
            }
            var query2 = from a in tc_ArticleRepository.Table
                         join c in tc_ArticlecateRepository.Table on a.cateId equals c.id
                         join u in tc_AdminRepository.Table on a.author equals u.id into userGroup
                         from user in userGroup.DefaultIfEmpty()
                         where c.id == articleInfo.cateId && a.id < articleInfo.id && a.status == 1
                         orderby a.id descending
                         select new SimpleArticleInfo()
                         {
                             id = a.id,
                             title = a.title,
                             userImage = user == null ? "/images/user.png" : user.headimg,
                             thumb = a.thumb,
                             username = user.nickname
                         };
            articleInfo.lastModel = await query2.FirstOrDefaultAsync();
            var query3 = from a in tc_ArticleRepository.Table
                         join c in tc_ArticlecateRepository.Table on a.cateId equals c.id
                         join u in tc_AdminRepository.Table on a.author equals u.id into userGroup
                         from user in userGroup.DefaultIfEmpty()
                         where c.id == articleInfo.cateId && a.id > articleInfo.id && a.status == 1
                         orderby a.id ascending
                         select new SimpleArticleInfo()
                         {
                             id = a.id,
                             title = a.title,
                             userImage = user == null ? "/images/user.png" : user.headimg,
                             thumb = a.thumb,
                             username = user.nickname
                         };
            articleInfo.nextModel = await query3.FirstOrDefaultAsync();
            return articleInfo;
        }

        /// <summary>
        /// 后台编辑数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<int> EditInfo(tc_article model)
        {
            model.updateTime = DateTime.Now;
            Expression<Func<tc_article, object>>[] updatedProperties = {
                    p => p.updateTime,p=>p.description,p=>p.author, p=>p.status,
                    p=>p.author, p=>p.cateId, p=>p.content, p=>p.copyfrom, p=>p.description
                    , p=>p.hits, p=>p.intro, p=>p.iselite, p=>p.keyWords, p=>p.ontop, p=>p.subhead
                    , p=>p.thumb, p=>p.title
                };
            return await tc_ArticleRepository.UpdateByFieldsAsync(model, updatedProperties);
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<int> DeleteInfo(string ids)
        {
            var arr = ids.Split(",", StringSplitOptions.RemoveEmptyEntries);
            List<tc_article> list = new List<tc_article>();
            foreach (var item in arr)
            {
                list.Add(new tc_article() { id = Convert.ToInt32(item) });
                //删除文章量
                var articleModel = await tc_ArticleRepository.getByIdAsync(Convert.ToInt32(item));
                var cateModel = await tc_ArticlecateRepository.getByIdAsync(articleModel.cateId);
                cateModel.count--;
                await tc_ArticlecateRepository.UpdateAsync(cateModel);
            }

            return await tc_ArticleRepository.DeleteListByFieldsAsync(list);
        }


        /// <summary>
        /// 增加文章点击量
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task AddClickCount(int id, int hits)
        {
            tc_article article = new tc_article();
            article.id = id;
            hits++;
            article.hits = hits;
            Expression<Func<tc_article, object>>[] updatedProperties = {
                    p => p.hits
                };
            await tc_ArticleRepository.UpdateByFieldsAsync(article, updatedProperties);

            if (WebSiteTemplateConfig.WebSite_OpenDataCache)
            {
                var WebSite_UniqueIdentification = memoryCache.Get("WebSite_UniqueIdentification").ToString();
                RedisHelper.HSetAsync(WebSite_UniqueIdentification + WebSiteConfig.Redis_Article_Key + id.ToString(), "Hits", hits.ToString());
            }
        }


        /// <summary>
        /// 根据时间获取文章数量
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public async Task<int> GetCountByDate(DateTime? date)
        {
            if (date == null)
            {
                return await tc_ArticleRepository.CountAsync();
            }
            return await tc_ArticleRepository.Table.Where(x => x.createTime >= date).CountAsync();
        }

    }
}
